﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/*
 代理模式有以下几种常见的应用：

1、远程代理（Remote Proxy）为一个其他的地址空间里的对象提供一个本地代表，这样可以隐藏一个对象存在于不同地址空间的事实。

2、虚代理（Virtual Proxy）为一个创建开销很大的对象提供代理，在需要创建的时候再延迟创建。

3、保护代理（Protection Proxy）控制对原始对象的访问。

4、智能指引（Smart Reference）取代了简单的指针，它在访问对象时执行一些附加操作：

（1）增加引用计数（当引用计数为零时，自动释放该对象）

（2）当第一次引用一个持久对象时，将它装入内存。

（3）当访问一个实际对象前，检查它是否已经被锁定，用以确保它不能被其他对象改变。
*/

/*
 代理模式的优点：隐藏了访问某个对象的细节和复杂性，并且可以为对象添加一些额外的操作。

缺点：额外增加了一个对象，这也就意味着内存消耗会增加，并且因为是间接处理，所以处理速度也会下降。当然，这也增加系统的复杂度。

*/



//虚代理的示例，延迟加载图片：
namespace TestProxy
{
    public interface IImage
    {
        void Draw();
    }

    public class Image : IImage
    {
        public Image(string fileName)
        {
            //TODO:
            Debug.Log("Loading image");
        }
        public void Draw()
        {
            //TODO:
            Debug.Log("Drawing image");
        }
    }

    public class ImageProxy : IImage
    {
        private Image _realImage = null;
        private string _filePath;
        public ImageProxy(string filePath)
        {
            _filePath = filePath;
        }
        protected Image GetImage()
        {
            if (null == _realImage)
            {
                _realImage = new Image(_filePath);
            }
            return _realImage;
        }
        public void Draw()
        {
            GetImage().Draw();
        }
    }
}

namespace Porte
{
    //保护代理
    public interface IHero
    {
        int attack { get; set; }
        int maxHP { get; set; }
    }

    public class Hero : IHero
    {
        public int attack { get; set; }
        public int maxHP { get; set; }
    }

    public class HeroProxy : IHero
    {
        private Hero _realHero;
        public HeroProxy()
        {
            _realHero = new Hero();
            InitializeHeroData();
        }
        private void InitializeHeroData()
        {
            //TEST
            _realHero.attack = 10;
            _realHero.maxHP = 100;
        }
        public int attack
        {
            get
            {
                return _realHero.attack;
            }
            set
            {
                throw new System.Exception("Hero's attack is readonly!");
            }
        }
        public int maxHP
        {
            get
            {
                return _realHero.maxHP;
            }
            set
            {
                throw new System.Exception("Hero's attack is readonly!");
            }
        }
    }


}

public class Proxy : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

        Porte. HeroProxy hero = new Porte.HeroProxy();
        try
        {
            hero.attack = 255;
        }
        catch (System.Exception e)
        {
            Debug.Log(e);
        }
    }

 
}
